---
sidebar_position: 4
---

# Часть 3. Подключение по SSH

## Что такое SSH-ключ

:::info
Материал основан на статье [Авторизация на базе ключей SSH
| Академия Selectel](https://selectel.ru/blog/ssh-authentication/).
:::

Аббревиатура SSH означает Secure Shell, что дословно переводится как «безопасная оболочка». Если говорить точнее, SSH — это защищенный сетевой протокол с проверкой подлинности и шифрованием. Он используется для передачи файлов, управления сетью и удаленного доступа к операционной системе. Аббревиатура SSH также используется для описания набора инструментов, используемых для взаимодействия с одноименным протоколом.

Подключение через SSH можно просто охарактеризовать как подключение к командной строке удаленного узла. То есть любые команды, которые будут вводиться в терминал на основной машине будут работать так же, будто вы вводите их напрямую на удаленном узле, сидя с клавиатурой около него.

Так как SSH работает по системе «клиент-сервер», обязательное условие для работы этого протокола — наличие на удаленном узле демона SSH. Демон SSH — это ПО, которое прослушивает определенный сетевой порт и при прохождении аутентификации другим узлом создает необходимую среду для работы с ним.

В свою очередь на локальной машине должно быть установлено соответствующее ПО — SSH-клиент. Он взаимодействует с удаленным хостом и передает ему необходимые данные, которые нужны для прохождения аутентификации.

#### Структура ключа

Можно сказать, что определение "SSH-ключ" составное, так как на самом деле это два ключа — **открытый** и **закрытый**. На узле A создаются и хранятся оба ключа, а на узел B передается только копия публичного SSH-ключа, что позволяет подключаться к узлу B с узла A.

Ключи могут быть сгенерированы с помощью различных алгоритмов, которые поддерживает текущая версия протокола SSH. Например, если использован тип шифрования RSA, то файлы будут именоваться следующим образом:

- `id_rsa` — закрытый ключ,
- `id_rsa.pub` — публичный (открытый) ключ.

В чем же разница открытого и закрытого ключа?

#### Открытые и закрытые SSH-ключи

**Открытый** (он же **публичный**) ключ используется для шифрования данных при обращении к удаленному узлу. Проще говоря, это набор символов, при помощи которых мы шифруем информацию. Он доступен всем. Не стоит бояться того, что открытый ключ может попасть в чужие руки, так как наличие одного лишь публичного SSH-ключа не дает злоумышленнику никаких преимуществ. Открытый SSH-ключ хранится на удаленном узле.

**Закрытый** (**приватный**) SSH-ключ — это ключ к данным. Он расшифровывает сами сообщения. Хранится он на устройстве, которое будет подключаться к удаленному узлу (на котором находится открытый ключ). Приватный ключ ни в коем случае нельзя передавать в чужие руки, в том числе через мессенджеры или файлообменники, во избежание утечки информации и персональных данных. Также рекомендуем сразу установить пароль на закрытый ключ, чтобы обеспечить ему дополнительную защиту.

#### Как работает SSH-авторизация?

Давайте представим, что вы хотите подключиться к серверу с использованием SSH-ключа. Предварительно вы уже создали пару ключей и передали публичный ключ нам. Алгоритм взаимодействия будет следующим:

1. Вы должны изъявить свое желание подключиться к нам, то есть отправить запрос на подключение по TCP-порту.
2. В случае установки TCP-соединения мы обмениваемся информацией о версиях наших  SSH-протоколов. С помощью этой информации можно понять, какую именно конфигурацию (версию протоколов и алгоритмы работы) использовать. Самостоятельно узнать версию OpenSSH можно с помощью команды `ssh -V`.
3. После согласования мы (сервер) направляем вам (клиенту) открытый ключ. Теперь уже вы решаете, доверять такому ключу или нет. В случае положительного ответа мы с вами генерируем сеансовый ключ, который будет использоваться для симметричного шифрования канала. Этот ключ существует, только пока существует канал (текущая сессия).
4. Теперь следует аутентифицировать вас. Для этого вы отсылаете нам свой открытый ключ. Мы в свою очередь проверяем его со своим списком открытых SSH-ключей. Если совпадение найдено, мы генерируем случайное число, шифруем его открытым ключом и отправляем обратно. Вы как клиент расшифровываете сообщение закрытым ключом и отправляете полученные данные нам. В случае совпадения присланного числа с первоначальным аутентификация признается успешной.

![ssh-auth](./images/ssh-auth.png)

Поздравляем! Теперь вам открыт доступ на сервер.

### Создание SSH-ключа

#### Параметры утилиты ssh-keygen

В Linux для создания SSH-ключей используется команда `ssh-keygen`. Далее приведены наиболее популярные параметры для этой команды и их описание.

По умолчанию `ssh-keygen` использует в качестве параметра `-t` именно RSA, так как этот алгоритм обеспечивает наилучшую совместимость из всех, но требует большего размера ключа для обеспечения достаточной безопасности. Длина ключа по умолчанию составляет 3072 бит, но вы можете самостоятельно задать его размер от 1024 до 16384 бит с помощью опции `-b` команды `ssh-keygen`.

##### `-C comment`

Создание нового комментария. Например, одной из самых известных команд является добавление комментария с информацией о том, кто, на какой машине и когда создал ключ:

```bash
ssh-keygen -C "$(whoami)@$(uname -n)-$(date -I)"
```

##### `-p`

Если указать данный параметр при вводе `ssh-keygen`, то вам будет предложено изменить старую секретную фразу на новую. Ввод команды будет выглядеть следующим образом:

```bash
ssh-keygen -p
```

Также вы можете задать все параметры для изменения секретной фразы сразу:

```bash
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
```

##### `-t type`

Задает тип создаваемого ключа. Чтобы узнать какие типы доступны для вашей версии, введите: 

```bash
ssh-keygen -t ?
```

##### `-v`

Подробный режим. ssh-keygen будет печатать отладочные сообщения о ходе выполнения. Несколько опций `-v` увеличивают степень подробности информации (максимум 3).

#### Утилиты для создания SSH-ключа

Далее мы создадим RSA ключ, добавим публичную часть на ВМ и подключимся с помощь него по SSH к ВМ. Сделаем это тремя способами:

- С помощью терминала и утилит Linux.
- С помощью утилит, предоставляемых [PuTTY](https://www.putty.org/);
- С помощью [SSH-агента PowerShell](https://learn.microsoft.com/ru-ru/powershell/scripting/learn/remoting/ssh-remoting-in-powershell-core?view=powershell-7.3);

##### Генерация SSH-ключей в Linux

Процесс создания SSH-ключей на базе Linux предельно прост. Вам необходимо лишь указать некоторые параметры, которые мы опишем далее.

Мы будем создавать ключ RSA. При вводе команды `ssh-keygen` опцию `-t` RSA можно не указывать явно, так как RSA является алгоритмом по умолчанию.

```bash
ssh-keygen
```

```bash
Generating public/private RSA key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
```

В последней строке вам предлагается выбрать путь, куда будут сохранены ключи. Если оставить поле пустым, будут созданы файлы с именами `id_rsa.pub` и `id_rsa`.

```bash
Enter passphrase (empty for no passphrase):
```

В данной строке предлагается создать кодовую фразу. Оставив строку пустой, дополнительной защиты не будет. 

С одной стороны, не вводить кодовую фразу опасно. Если закрытый ключ попадет в руки злоумышленников, то у них может появиться доступ к серверу. В то же время, если вы введете кодовую фразу, в будущем это может доставить вам неудобства. Пароль придется вводить каждый раз при использовании SSH-подключения с этим ключом. Поэтому использование кодовой фразы остается на ваше усмотрение.

Как мы упоминали ранее, кодовую фразу можно будет установить (или заменить) самостоятельно, введя `ssh-keygen -p`, когда ключ уже будет создан:

![ssh-keygen-1](./images/ssh-keygen-1.png)

Созданные файлы хранятся в директории `/home/<имя пользователя>/.ssh/`.

Посмотреть публичный ключ текущего пользователя можно с помощью команды:

```bash
cat ~/.ssh/id_rsa.pub
```

![ssh-keygen-2](./images/ssh-keygen-2.png)

##### Генерация SSH-ключей в PuTTY

Если вы хотите создать SSH-ключи на базе ОС Windows, самым популярным решением для этого будет использование программного обеспечения Putty. Скачать его можно с официального сайта по [ссылке](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) (актуальная версия на момент написания материала — `0.79, released on 2023-08-26`). После установки программы вам будет доступно несколько `.exe` файлов.

Для создания SSH-ключей откройте `puttygen.exe`:

![puttygen-1](./images/puttygen-1.png)

Выберите необходимый тип ключа и задайте его размер. Мы будем использовать RSA с длиной 2048:

![puttygen-2](./images/puttygen-2.png)

Далее нажмите `Generate` и водите мышкой по экрану в свободной зоне до тех пор, пока генерация SSH-ключей не будет завершен. Это необходимо делать для того, чтобы задать псевдослучайность при создании ключей:

![puttygen-3](./images/puttygen-3.png)

После генерации ключа вы можете вписать комментарий и кодовую фразу.

Далее необходимо сохранить на диск открытый и закрытый SSH-ключи, для этого нажмите на соответствующие кнопки в окне программы. Вы можете самостоятельно выбрать путь, куда сохранять данные ключи:

![puttygen-4](./images/puttygen-4.png)

Для публичного используйте имя `id_rsa.pub`. Для приватного `id_rsa.ppk`.

Putty сохраняет закрытые ключи с разрешением `.ppk`, что означает, что такой ключ можно будет использовать только с Putty. Чтобы сохранить секретный ключ в формате, пригодном для OpenSSH, нужно во вкладке Конвертация выбрать пункт "Экспортировать ключ в формате OpenSSH (новый формат)" и указать расположение нового файла (старый формат при конвертации из `.pkk` в OpenSSH сохраняет не все поля — например, комментарий):

![puttygen-5](./images/puttygen-5.png)

Посмотреть публичный ключ можно в окне PuTTY Key Generator. Скопировать можно через правую кнопку мыши, вызывав тем самым контекстное меню:

![puttygen-6](./images/puttygen-6.png)

![puttygen-7](./images/puttygen-7.png)


##### Генерация SSH-ключей в Windows с помощью OpenSSH

Не так давно в ОС Windows добавили возможность использования инструментов OpenSSH. Пакет добавлен в ОС, начиная с Windows 10 и Windows Server 2019.

Установить клиент OpenSSH можно с помощью следующей команды в PowerShell (PowerShell нужно запустить от имени администратора):

```powershell
Add-WindowsCapability -Online -Name OpenSSH.Client
```

![powershell-ssh-keygen-1](./images/powershell-ssh-keygen-1.png)

![powershell-ssh-keygen-2](./images/powershell-ssh-keygen-2.png)

Проверить статус компонента можно командой (также от администратора):

```powershell
Get-WindowsCapability -Online | ? Name -like 'OpenSSH.Client*'
```

![powershell-ssh-keygen-3](./images/powershell-ssh-keygen-3.png)

Если в ответе команды статус `Installed`, то загрузка выполнена успешно.

Генерация SSH-ключей происходит таким же образом, как и в ОС Linux, с помощью ssh-keygen (команды нужно выполнять от имени пользователя):

![powershell-ssh-keygen-4](./images/powershell-ssh-keygen-4.png)

Созданные ключи можно найти в папке `C:\Users\<имя пользователя>\.ssh`, если она не была изменена при генерации. Посмотреть ключ можно с помощью команды `cat`:

![powershell-ssh-keygen-5](./images/powershell-ssh-keygen-5.png)

### Копирование открытого ключа на сервер

#### Linux

Данный метод подойдет тем, чья ОС поддерживает команду SSH-Copy-ID, и удаленный сервер имеет доступ по SSH без ключа. Если это не так, попробуйте использовать второй или третий способ.

Синтаксис команды выглядит следующим образом:

```bash
ssh-copy-id {USERNAME}@{IP-ADDRESS-OR-FQDN} -p {PORT}
```

Замените `{IP-ADDRESS-OR-FQDN}` на IP-адрес или полное доменное имя (полное доменное имя) сервера, на которое вы хотите скопировать открытый ключ, `{USERNAME}` - имя пользователя, к которому хотите подключиться, `{PORT}` - порт SSH (по умолчанию `22`).

:::caution
Далее используйте имя пользователя (`{USERNAME}`), которого вы ранее сделали суперпользователем (`ansible`).
:::

Обратите внимание на последние строки вывода:

![linux-ssh-copy-1](./images/linux-ssh-copy-1.png)

Наш клиент запрашивает разрешение на продолжение подключения к удаленному узлу, так как встречает его впервые. Необходимо ввести `yes`. После успешного подключения ключи будут добавлены и мы увидим приглашение к вводу пароля. Вводим пароль и получаем подтверждение о том, что теперь мы можем подключиться к удаленному узлу Linux с помощью команды `ssh`:

![linux-ssh-copy-2](./images/linux-ssh-copy-2.png)

Чтобы проверить, действительно ли скопировался открытый ключ, найдем искомый файл `authorized_keys` на удаленном узле и посмотрим его содержимое, так как именно в него добавляются открытые SSH-ключи. Содержится он в домашней директории в скрытой папке `.ssh`. Посмотреть его можно так:

```bash
cat ~/.ssh/authorized_keys
```

![linux-ssh-copy-3](./images/linux-ssh-copy-3.png)

#### PuTTY {#copy-putty}

> Альтернативный способ показан в [статье](https://selectel.ru/blog/ssh-authentication/). В нем используется только `putty.exe` без Pageant. 

Скопируйте публичный ключ, который отображается в `puttygen.exe`:

![putty-ssh-copy-1](./images/putty-ssh-copy-1.png)

Затем следует любым доступным вам способом подключиться к удаленному серверу, куда необходимо скопировать открытый SSH-ключ.

В домашней директории создайте файл `putty_id_rsa.pub`. Сделать это можно с помощью редактора Nano:

```bash
nano putty_id_rsa.pub
```

Далее вставьте содержимое из буфера обмена с помощью нажатия правой клавишы мыши в окне или с помощь комбинации клавиш `shift+insert`:

![putty-ssh-copy-2](./images/putty-ssh-copy-2.png)

Сохраните содержимое с помощью комбинаций `ctrl+x`. Подтвердите, что вы хотите сохранить содержимое из буфера на диск нажав на клавишу `y`:

![putty-ssh-copy-3](./images/putty-ssh-copy-3.png)

Далее подтвердите с помощью клавиши `enter` путь сохранения:

![putty-ssh-copy-4](./images/putty-ssh-copy-4.png)

Затем требуется добавить наш публичный ключ в `authorized_keys`.

```bash
cat putty_id_rsa.pub >> ~/.ssh/authorized_keys
```

С помощью `cat ~/.ssh/authorized_keys` проверьте, что ключ был действительно добавлен в `authorized_keys`:

![putty-ssh-copy-5](./images/putty-ssh-copy-5.png)

Мы уже скопировали открытый SSH-ключ, сгенерированный с помощью Putty, на удаленный узел. Теперь необходимо произвести подключение.

Для этого откройте Pageant и добавьте туда приватный ключ, сгенерированный с помощью `puttygen.exe`:

![putty-ssh-copy-6](./images/putty-ssh-copy-6.png)

Pageant по умолчанию после запуска прячется в значках панели управления рядом с часами:

![putty-ssh-copy-7](./images/putty-ssh-copy-7.png)

Вызовите контекстное меню с помощью правой кнопки мышки и выберите пункт "Add key":

![putty-ssh-copy-8](./images/putty-ssh-copy-8.png)

Откройте ключ в формате `.ppk`:

![putty-ssh-copy-9](./images/putty-ssh-copy-9.png)

Чтобы убедиться, что ключ был добавлен, необходимо в том же контекстном меню Pageant выбрать пункт "View Keys":

![putty-ssh-copy-10](./images/putty-ssh-copy-10.png)

Откроется окно с активным ключами:

![putty-ssh-copy-11](./images/putty-ssh-copy-11.png)

Теперь можно установить сессию, которая будет для подключения использовать наш приватный ключ. В контекстном Pageant меню выберите "New Session":

![putty-ssh-copy-12](./images/putty-ssh-copy-12.png)

Введите IP-адрес удаленного узла, имя пользователя и порт для подключения, а также проверьте, что в качестве типа подключения выбран SSH:

![putty-ssh-copy-13](./images/putty-ssh-copy-13.png)

Нажмите "Open". При первом подключении вам потребуется подтвердить, что удаленный узел вам известен и его можно добавить в известные:

![putty-ssh-copy-14](./images/putty-ssh-copy-14.png)

При успешном подключении появится приглашение к вводу команд:

![putty-ssh-copy-15](./images/putty-ssh-copy-15.png)

#### PowerShell

> Материал основан на статье [Windows 10 OpenSSH Equivalent of ssh-copy-id | Christopher Hart](https://chrisjhart.com/Windows-10-ssh-copy-id/).
>
> Альтернативный поход смотрите в [статье](https://selectel.ru/blog/ssh-authentication/).

Далее мы используем приведенную ниже онлайн-команду PowerShell, чтобы скопировать содержимое открытого ключа `id_rsa.pub` на удаленное устройство Linux. Замените `{IP-ADDRESS-OR-FQDN}` на IP-адрес или полное доменное имя (полное доменное имя) сервера, на которое вы хотите скопировать открытый ключ, `{USERNAME}` - имя пользователя, к которому хотите подключиться, `{PORT}` - порт SSH (по умолчанию `22`):

```powershell
type $env:USERPROFILE\.ssh\id_rsa.pub | ssh {USERNAME}@{IP-ADDRESS-OR-FQDN} -p {PORT} "cat >> .ssh/authorized_keys"
```

Далее у вас спросят пароль от пользователя. Пример того, как выполняется копирование ключа:

![powershell-ssh-copy-1](./images/powershell-ssh-copy-1.png)

Убедитесь, что вы можете подключиться по SSH к удаленному устройству Linux с помощью команды `ssh`. Ниже показан пример подключения к удаленному устройству Linux по IP-адресу. Обратите внимание, что нам не нужно было вводить пароль, чтобы установить SSH-подключение к удаленному устройству Linux:

![powershell-ssh-copy-2](./images/powershell-ssh-copy-2.png)


### Устранение неполадок

Возможные неполадки и способы их решения представлены в статье [Авторизация на базе ключей SSH | Академия Selectel](https://selectel.ru/blog/ssh-authentication/).
